package com.woniu.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.dto.ProductDto;
import com.woniu.entity.Product;
import com.woniu.mapper.ProductMapper;
import com.woniu.publisher.ProductPublisher;
import com.woniu.service.ProductService;
import com.woniu.util.ConstantUtil;
import com.woniu.util.ResponseEnum;
import com.woniu.util.ResponseUtil;

import com.woniu.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProductServiceImpl implements ProductService {
    @Resource
    private ProductMapper productMapper;
    @Resource
    private RedisTemplate redisTemplateInit;

    @Override
    public ResponseUtil findAllVo() {
        List<ProductVo> all = productMapper.findAllVo();
        return !all.isEmpty() ? ResponseUtil.get(ResponseEnum.OK, all)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    /**
     * 增加库存（用于订单取消/退款）
     */
    @Transactional
    public boolean increaseStock(Integer productId, Integer addNum) {
        if (productId == null || addNum == null || addNum <= 0) {
            return false;
        }

        String redisKey = ConstantUtil.REDIS_PRODUCT_KEY;

        // 1️⃣ 第一次删除 Redis 缓存（删除整个 hash）
        redisTemplateInit.delete(redisKey);
        log.info("🗑️ 第一次删除缓存（增加库存前）: {}", redisKey);

        // 2️⃣ 数据库增加库存
        int result = productMapper.increaseStock(Long.valueOf(productId), addNum);
        if (result <= 0) {
            log.warn("商品ID={} 增加库存失败，可能商品不存在", productId);
            return false;
        }

        // 3️⃣ 延迟 1 秒后第二次删除缓存（模仿 update 方法）
        new Thread(() -> {
            try {
                Thread.sleep(1000); // 延迟 1 秒
                redisTemplateInit.delete(redisKey);
                log.info("✅ 延迟双删完成（增加库存后）: {}", redisKey);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("延迟双删线程被中断");
            }
        }).start();

        return true;
    }

    @Override
    public PageInfo findAll(ProductDto productDto,Integer pageNum , Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<Product> allProduct = productMapper.findAllProduct(productDto);
        return new PageInfo<>(allProduct);
    }

    @Override
    public ResponseUtil categoryFindAll(Integer categoryId) {
        List<Product> products = productMapper.categoryFindAll(categoryId);
        return ResponseUtil.get(ResponseEnum.OK, products);
    }
    @Override
    public List<Product> findAllProduct(ProductDto productDto) {
        return productMapper.findAllProduct(productDto);
    }



    @Override
    public int delete(Integer productId) {
        return productMapper.delete(productId);
    }

    @Override
    public int add(Product product) {
        // 只允许添加成品，次品无法添加
        if ("2".equals(product.getType())) {
            throw new RuntimeException("只能添加成品，不能添加次品");
        }
        return productMapper.add(product);
    }


    @Override
    public Product findByProductId(Integer productId) {
        if (productId == null) {
            return null;
        }

        String redisKey = ConstantUtil.REDIS_PRODUCT_KEY;
        String fieldKey = ConstantUtil.REDIS_PRODUCT_KEY + productId;

        // 1. 先从 Redis 的 Hash 中获取
        Product product = (Product) redisTemplateInit.opsForHash().get(redisKey, fieldKey);

        if (product != null) {
            // 缓存命中，直接返回
            return product;
        }

        // 2. 缓存未命中，查数据库
        product = productMapper.findByProductId(productId);

        if (product != null) {
            // 3. 将查到的结果写回 Redis，设置到 Hash 中，方便后续查询
            redisTemplateInit.opsForHash().put(redisKey, fieldKey, product);
        }

        return product;
    }

    @Override
    public ResponseUtil update(Product product) throws InterruptedException {
        redisTemplateInit.delete(ConstantUtil.REDIS_PRODUCT_KEY);
        int update = productMapper.update(product);
        Thread.sleep(1000);
        redisTemplateInit.delete(ConstantUtil.REDIS_PRODUCT_KEY);
        return update > 0 ? ResponseUtil.get(ResponseEnum.OK) : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil findAll2() {
        List<Product> productList = new ArrayList<>();
        Map<String, Product> map =  redisTemplateInit.opsForHash().entries(ConstantUtil.REDIS_PRODUCT_KEY);
        if (map.isEmpty()) {
            productList = productMapper.findAll();
            Map<String, Product> productMap = productList.stream().collect(Collectors.toMap(
                    e -> ConstantUtil.REDIS_PRODUCT_KEY + e.getProductId(),
                    e -> e
            ));
            redisTemplateInit.opsForHash().putAll(ConstantUtil.REDIS_PRODUCT_KEY, productMap);
        }else {
            productList.addAll(map.values());
        }
        return ResponseUtil.get(ResponseEnum.OK,productList );
    }

    @Resource
    private ProductPublisher productPublisher;

    /**
     * 核心方法：筛选过期商品列表
     */
    @Override
    public List<Product> getExpiredProducts() {
        List<Product> productList = new ArrayList<>();
        List<Product> expiredList = new ArrayList<>(); // 最终返回给前端的过期商品列表

        // 1. 从缓存获取商品
        Map<Object, Object> map = redisTemplateInit.opsForHash().entries(ConstantUtil.REDIS_PRODUCT_KEY);
        if (map != null && !map.isEmpty()) {
            for (Object value : map.values()) {
                Product product = parseProduct(value);
                if (product != null) {
                    productList.add(product);
                }
            }
        } else {
            // 缓存为空时从数据库加载
            productList = productMapper.findAll();
            // 回写缓存
            writeProductsToCache(productList);
        }

        // 2. 筛选条件：updateTime不为null + 超过1天未更新 + 库存>0
        Date now = new Date();
        long oneDayMillis = 24 * 60 * 60 * 1000; // 1天的毫秒数

        for (Product product : productList) {
            Date updateTime = product.getUpdateTime();
            BigDecimal stock = product.getStock();

            // 条件1：updateTime不为null
            if (updateTime == null) {
                continue;
            }

            // 条件2：库存>0（BigDecimal判断）
            if (stock == null || stock.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }

            // 条件3：超过1天未更新
            long timeDiff = now.getTime() - updateTime.getTime();
            if (timeDiff > oneDayMillis) {
                expiredList.add(product);
            }
        }
        return expiredList; // 返回给前端
    }

    /**
     * 定时任务：每天自动检查并更新过期商品状态
     */
    @Scheduled(cron = "0 0 6 * * ?")  // 每10秒执行一次
    public void dailyCheckExpiredProducts() {
        // 添加日志，验证是否触发
        log.info("定时任务执行了！当前时间：{}", new Date());
        try {
            List<Product> expiredList = getExpiredProducts();
            log.info("定时任务检查到临期商品数量：{}", expiredList.size());
        } catch (Exception e) {
            log.error("定时任务执行失败", e);  // 捕获异常，避免任务中断
        }
    }

    /**
     * 解析缓存中的商品对象
     */
    private Product parseProduct(Object value) {
        if (value instanceof Product) {
            return (Product) value;
        } else if (value instanceof String) {
            return com.alibaba.fastjson.JSON.parseObject((String) value, Product.class);
        }
        return null;
    }

    /**
     * 将商品列表写入缓存
     */
    private void writeProductsToCache(List<Product> productList) {
        if (productList == null || productList.isEmpty()) {
            return;
        }
        for (Product product : productList) {
            redisTemplateInit.opsForHash().put(
                    ConstantUtil.REDIS_PRODUCT_KEY,
                    String.valueOf(product.getProductId()),
                    com.alibaba.fastjson.JSON.toJSONString(product)
            );
        }
        redisTemplateInit.expire(ConstantUtil.REDIS_PRODUCT_KEY, 24, java.util.concurrent.TimeUnit.HOURS);
    }
}
